package game.Sprites;


import game.Utils.GraphicsUtils;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.image.Image;

import java.awt.image.BufferedImage;
import java.rmi.server.ExportException;
import java.util.List;


public class SpriteSheet {
    int cols, rows; // Number of columns and rows
    Image[] spriteList; // Array holding all the sprite images in the spritesheet

    /**
     * Constructor of SpriteSheet class
     * @param sheet BufferedImage containing the spritesheet
     * @param cols Number of columns in the spritesheet image
     * @param rows Number of rows in the spritesheet image.
     * @throws Exception Invalid number of columns or rows.
     */
    public SpriteSheet(BufferedImage sheet, int cols, int rows) throws Exception {
        if(cols <= 0 || rows <= 0){
            throw new Exception("SpriteSheet cols and rows must be larger than 0.");
        }

        this.cols = cols;
        this.rows = rows;

        this.genSpriteList(SwingFXUtils.toFXImage(sheet,null));
    }

    /**
     * Initializes and fills the spriteList given the original spritesheet image, following the number of columns and
     * rows in this.cols and this.rows.
     * @param sheet The image containing the spritesheet.
     */
    protected void genSpriteList(Image sheet){
        // Instantiate spriteList with right size
        spriteList = new Image[cols*rows];


        // Create different sprites in list
        for(int i = 0; i < this.rows; i++) {
            for (int j = 0; j < this.cols; j++) {
                int width = (int)sheet.getWidth() / cols; // individual sprite width
                int height = (int)sheet.getHeight() / rows; // individual sprite height
                spriteList[j + i*cols] = GraphicsUtils.getSubimage(sheet, j*width, i*height, width, height);
            }
        }
    }

    /**
     * Returns a specific sprite from the spritesheet, given its index.
     * @param i Index of the sprite in the spritesheet
     * @return The sprite located in the index i in the spritesheet.
     * @throws IndexOutOfBoundsException Index is out of bounds
     */
    public Image get(int i) throws IndexOutOfBoundsException {
        if(i < 0 || i > cols*rows){
            throw new IndexOutOfBoundsException();
        }else{
            return spriteList[i];
        }
    }

    /**
     * Returns a specific sprite from the spritesheet, given its position in the sheet (i, j).
     * @param i Vertical index of the sprite in the spritesheet
     * @param j Horizontal index of the sprite in the spritesheet
     * @return  The sprite located in the (i, j) position in the spritesheet.
     * @throws IndexOutOfBoundsException Index is out of bounds
     */
    public Image get(int i, int j) throws IndexOutOfBoundsException {
        if(i < 0 || j < 0 || i > rows || j > cols){
            throw new IndexOutOfBoundsException();
        }else{
            return spriteList[j + i*cols];
        }
    }

    /**
     *
     * @return The number of columns in the spritesheet.
     */
    public int getCols(){
        return this.cols;
    }

    /**
     *
     * @return The number of rows in the spritesheet.
     */
    public int getRows(){
        return this.rows;
    }
}
